{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `HMM`生成模型\n",
    "给定句子 $S$，对应的输出词性序列 $T$，`HMM`模型的联合概率：\n",
    "$$\n",
    "\\begin{align}\n",
    "P(T|S) &= \\frac{P(S|T)\\cdot P(T)}{P(S)}\\\\\n",
    "P(S,T) &= P(S|T)\\cdot P(T)\\\\\n",
    "       &= \\prod_{i=1}^{n}P(w_i|T)\\cdot P(T)\\\\\n",
    "       &= \\prod_{i=1}^{n}P(w_i|t_i)\\cdot P(T)\\\\\n",
    "       &= \\prod_{i=1}^{n}P(w_i|t_i)\\cdot P(t_i|t_{i-1})\\\\       \n",
    "\\end{align}\n",
    "$$\n",
    "> 首先贝叶斯公式展开，然后利用 ***以下假设*** 简化：<br/>\n",
    "- 由词之间相互独立假设，得到 $\\prod_{i=1}^{n}P(w_i|T)$ \n",
    "- 由单词概率仅依赖于其自身的标签，得到**发射`(emission)`概率** $\\prod_{i=1}^{n}P(w_i|t_i)$ \n",
    "- 由马尔可夫假设，使用 `bi-gram` 得到**转移`(transition)`概率** $P(t_i|t_{i-1})$\n",
    "\n",
    "--------\n",
    "\n",
    "目标函数：\n",
    "\n",
    "$$\n",
    "(\\hat{t_1},\\hat{t_2}...\\hat{t_n})=arg max\\prod_{i=1}^{n}P(w_i|t_i)\\cdot P(t_i|t_{i-1})\n",
    "$$\n",
    "\n",
    "---------\n",
    "综上，`HMM`假设了两类特征：当前词性与上一词性的关系，当前词与当前词性的关系<br/>\n",
    "HMM的学习过程就是在训练集中学习这两个概率矩阵，大小分别为`(t,t),(w,t)`，`w`为单词的个数，`t`为词性的个数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 实战：词性标注\n",
    "- 词性标注`(Part-Of-Speech tagging, POS tagging)`，判断句子中单词的词性：谓词、虚词、代词、感叹词等\n",
    "- 本质上属于分类问题，将句子中的单词按词性分类\n",
    "- 因此需要词性标注好的语料库，其中给定句子$s=w_1w_2...w_n$及对应的词性 $t=z_1z_2...z_n$\n",
    "> 语料格式：每一行为词+词性，特殊符号 `,` 等表示句子结尾\n",
    "```\n",
    "'Newsweek/NNP\\n',\n",
    "',/,\\n',\n",
    "'trying/VBG\\n',\n",
    "'to/TO\\n',\n",
    "'keep/VB\\n',\n",
    "'pace/NN\\n',\n",
    "'with/IN\\n',\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T07:23:43.085651Z",
     "start_time": "2020-05-27T07:23:43.079645Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Newsweek/NNP\\n',\n",
       " ',/,\\n',\n",
       " 'trying/VBG\\n',\n",
       " 'to/TO\\n',\n",
       " 'keep/VB\\n',\n",
       " 'pace/NN\\n',\n",
       " 'with/IN\\n']"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 语料样本\n",
    "open('../datasets/pos_tagging_data.txt','r').readlines(50)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 创建词汇表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-04-30T07:57:39.107264Z",
     "start_time": "2020-04-30T07:57:39.098519Z"
    }
   },
   "outputs": [],
   "source": [
    "# 创建字典，便于将文本数值化\n",
    "\n",
    "tag2id, id2tag = {}, {}\n",
    "word2id, id2word = {}, {}\n",
    "\n",
    "for line in open('../datasets/pos_tagging_data.txt', 'r'):\n",
    "    items = line.split('/')\n",
    "    word, tag = items[0], items[1].rstrip()\n",
    "\n",
    "    if word not in word2id:\n",
    "        word2id[word] = len(word2id)\n",
    "        id2word[len(id2word)] = word\n",
    "    if tag not in tag2id:\n",
    "        tag2id[tag] = len(tag2id)\n",
    "        id2tag[len(tag2id)] = tag\n",
    "\n",
    "M = len(word2id)  # 词典的大小\n",
    "N = len(tag2id)  # 词性的种类\n",
    "\n",
    "print(M,N)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 发射矩阵和转移矩阵\n",
    "- 基于语料库，计算发射矩阵和转移矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-04-30T07:57:50.768365Z",
     "start_time": "2020-04-30T07:57:50.376141Z"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "pi = np.zeros(N)  # 每个 tag 出现在句首的概率\n",
    "A = np.zeros((N, M))  # A[i][j],给定 tag i,出现单词 j 的概率\n",
    "B = np.zeros((N, N))  # B[i][j],词性为 tag i 时，其后单词的词性为 tag j 的概率\n",
    "\n",
    "prev_tag = \"\"\n",
    "for line in open('../datasets/pos_tagging_data.txt', 'r'):\n",
    "    items = line.split('/')\n",
    "    wordId, tagId = word2id[items[0]], tag2id[items[1].rstrip()]\n",
    "\n",
    "    if prev_tag == \"\":  # 判断句子的开始\n",
    "        pi[tagId] += 1\n",
    "        A[tagId][wordId] += 1\n",
    "    else:\n",
    "        A[tagId][wordId] += 1\n",
    "        B[tag2id[prev_tag]][tagId] += 1\n",
    "\n",
    "    if items[0] == \".\":\n",
    "        prev_tag = \"\"\n",
    "    else:\n",
    "        prev_tag = items[1].rstrip()\n",
    "\n",
    "# 转化成概率\n",
    "pi = pi / sum(pi)\n",
    "for i in range(N):\n",
    "    A[i] /= sum(A[i])\n",
    "    B[i] /= sum(B[i])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-04-30T07:57:53.340354Z",
     "start_time": "2020-04-30T07:57:53.336173Z"
    }
   },
   "outputs": [],
   "source": [
    "pi"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 维特比算法求解最优标注"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-04-30T07:57:57.537197Z",
     "start_time": "2020-04-30T07:57:57.533856Z"
    }
   },
   "outputs": [],
   "source": [
    "def log_(v):\n",
    "    if v==0:\n",
    "        return np.log(v+0.000001)\n",
    "    return np.log(v)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-04-30T07:58:01.639592Z",
     "start_time": "2020-04-30T07:58:01.633379Z"
    }
   },
   "outputs": [],
   "source": [
    "from math import log\n",
    "\n",
    "\n",
    "def viterbi(x, pi, A, B):  # x 为输入句子，\"I like playing soccer\"\n",
    "    x = [word2id[word] for word in x.split(\" \")]\n",
    "    T = len(x)\n",
    "\n",
    "    dp = np.zeros((T, N))  # 默认浮点数\n",
    "    ptr = np.array([[0 for x in range(N)] for y in range(T)])  # 整数\n",
    "\n",
    "    for j in range(N):\n",
    "        dp[0][j] = log_(pi[j]) + log_(A[j][x[0]])  # 需要添加平滑项\n",
    "\n",
    "    for i in range(1, T):\n",
    "        for j in range(N):\n",
    "            dp[i][j] = float('-inf')\n",
    "            for k in range(N):\n",
    "                score = dp[i - 1][k] + log_(B[k][j]) + log_(A[j][x[i]])\n",
    "                if score > dp[i][j]:\n",
    "                    dp[i][j] = score\n",
    "                    ptr[i][j] = k\n",
    "\n",
    "    # decoding：找出最好的 tag sequence\n",
    "    best_seq = [0] * T\n",
    "    # step1：找出最后一个单词的词性\n",
    "    best_seq[T - 1] = np.argmax(dp[T - 1])\n",
    "\n",
    "    # step2：从后向前循环依次找出每个单词的词性\n",
    "    for i in range(T - 2, -1, -1):\n",
    "        best_seq[i] = ptr[i + 1][best_seq[i + 1]]\n",
    "\n",
    "    return [id2tag[id] for id in best_seq]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-04-30T07:58:02.483280Z",
     "start_time": "2020-04-30T07:58:02.451065Z"
    }
   },
   "outputs": [],
   "source": [
    "x = \"I like play soccer\"\n",
    "viterbi(x,pi,A,B)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 实战：命名实体识别\n",
    "基于人民日报语料，词汇表及标签已经处理完成"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 根据语料获取转移矩阵与发射矩阵\n",
    "语料每一行为一个子句，每个子句中用空格隔开标注好的单字，单字与其词性用`/`连接"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:25:39.223834Z",
     "start_time": "2020-05-27T08:25:39.217111Z"
    }
   },
   "outputs": [],
   "source": [
    "with open(\"../datasets/ner/renmin/vocab.pkl\", 'rb') as inp:\n",
    "    token2idx = pickle.load(inp)\n",
    "    idx2token = pickle.load(inp)\n",
    "\n",
    "with open(\"../datasets/ner/renmin/tags.pkl\", \"rb\") as inp:\n",
    "    tag2idx = pickle.load(inp)\n",
    "    idx2tag = pickle.load(inp)    \n",
    "\n",
    "# 模型参数    \n",
    "N = len(tag2idx)\n",
    "M = len(token2idx)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:26:12.522633Z",
     "start_time": "2020-05-27T08:26:10.334882Z"
    }
   },
   "outputs": [],
   "source": [
    "import codecs\n",
    "\n",
    "\n",
    "def train_hmm(data_file):\n",
    "    input_data = codecs.open(data_file, 'r', 'utf-8')\n",
    "\n",
    "    pi = np.zeros(N)  # 每个 tag 出现在句首的概率\n",
    "    A = np.zeros((N, M))  # A[i][j],给定 tag i,出现单词 j 的概率\n",
    "    B = np.zeros((N, N))  # B[i][j],词性为 tag i 时，其后单词的词性为 tag j 的概率\n",
    "\n",
    "    for line in input_data.readlines():\n",
    "        line = line.strip().split()\n",
    "        tokens = [token2idx[string.split('/')[0].strip()] for string in line]\n",
    "        tags = [tag2idx[string.split('/')[1].strip()] for string in line]\n",
    "\n",
    "        for idx in range(len(tokens)):\n",
    "            if idx == 0:\n",
    "                pi[tags[idx]] += 1\n",
    "                A[tags[idx]][tokens[idx]] += 1\n",
    "            else:\n",
    "                A[tags[idx]][tokens[idx]] += 1\n",
    "                B[tags[idx - 1]][tags[idx]] += 1\n",
    "\n",
    "    pi = pi / sum(pi)\n",
    "    A = A / A.sum(axis=-1).reshape(-1, 1)\n",
    "    B = B / B.sum(axis=-1).reshape(-1, 1)\n",
    "\n",
    "    return pi, A, B\n",
    "\n",
    "# data_file = '../datasets/ner/renmin/renmin4.txt'\n",
    "# pi, A, B = train_hmm(data_file)\n",
    "\n",
    "# with open('../models/ner/hmm.pkl', 'wb') as output:\n",
    "#     pickle.dump(pi, output)\n",
    "#     pickle.dump(A, output)    \n",
    "#     pickle.dump(B, output)    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:26:37.576814Z",
     "start_time": "2020-05-27T08:26:37.571454Z"
    }
   },
   "outputs": [],
   "source": [
    "with open('../models/ner/hmm.pkl', 'rb') as inp:\n",
    "    pi = pickle.load(inp)\n",
    "    A = pickle.load(inp)    \n",
    "    B = pickle.load(inp)    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:26:48.766117Z",
     "start_time": "2020-05-27T08:26:48.445659Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style  type=\"text/css\" >\n",
       "    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col0 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col1 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col2 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col3 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col4 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col5 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col6 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col7 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col8 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col9 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col0 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col1 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col2 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col3 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col4 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col5 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col6 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col7 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col8 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col9 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col0 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col1 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col2 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col3 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col4 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col5 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col6 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col7 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col8 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col9 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col0 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col1 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col2 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col3 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col4 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col5 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col6 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col7 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col8 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col9 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col0 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col1 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col2 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col3 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col4 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col5 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col6 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col7 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col8 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col9 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col0 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col1 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col2 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col3 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col4 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col5 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col6 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col7 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col8 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col9 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col0 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col1 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col2 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col3 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col4 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col5 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col6 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col7 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col8 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col9 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col0 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col1 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col2 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col3 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col4 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col5 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col6 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col7 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col8 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col9 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col0 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col1 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col2 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col3 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col4 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col5 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col6 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col7 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col8 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col9 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col0 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col1 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col2 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col3 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col4 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col5 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col6 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col7 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col8 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col9 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }</style><table id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966\" ><thead>    <tr>        <th class=\"blank level0\" ></th>        <th class=\"col_heading level0 col0\" >B_nt</th>        <th class=\"col_heading level0 col1\" >M_nt</th>        <th class=\"col_heading level0 col2\" >E_nt</th>        <th class=\"col_heading level0 col3\" >B_nr</th>        <th class=\"col_heading level0 col4\" >M_nr</th>        <th class=\"col_heading level0 col5\" >E_nr</th>        <th class=\"col_heading level0 col6\" >B_ns</th>        <th class=\"col_heading level0 col7\" >M_ns</th>        <th class=\"col_heading level0 col8\" >E_ns</th>        <th class=\"col_heading level0 col9\" >O</th>    </tr></thead><tbody>\n",
       "                <tr>\n",
       "                        <th id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966level0_row0\" class=\"row_heading level0 row0\" >B_nt</th>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col0\" class=\"data row0 col0\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col1\" class=\"data row0 col1\" >1.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col2\" class=\"data row0 col2\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col3\" class=\"data row0 col3\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col4\" class=\"data row0 col4\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col5\" class=\"data row0 col5\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col6\" class=\"data row0 col6\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col7\" class=\"data row0 col7\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col8\" class=\"data row0 col8\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row0_col9\" class=\"data row0 col9\" >0.000000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966level0_row1\" class=\"row_heading level0 row1\" >M_nt</th>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col0\" class=\"data row1 col0\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col1\" class=\"data row1 col1\" >0.740000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col2\" class=\"data row1 col2\" >0.260000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col3\" class=\"data row1 col3\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col4\" class=\"data row1 col4\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col5\" class=\"data row1 col5\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col6\" class=\"data row1 col6\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col7\" class=\"data row1 col7\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col8\" class=\"data row1 col8\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row1_col9\" class=\"data row1 col9\" >0.000000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966level0_row2\" class=\"row_heading level0 row2\" >E_nt</th>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col0\" class=\"data row2 col0\" >0.010000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col1\" class=\"data row2 col1\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col2\" class=\"data row2 col2\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col3\" class=\"data row2 col3\" >0.010000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col4\" class=\"data row2 col4\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col5\" class=\"data row2 col5\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col6\" class=\"data row2 col6\" >0.080000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col7\" class=\"data row2 col7\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col8\" class=\"data row2 col8\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row2_col9\" class=\"data row2 col9\" >0.890000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966level0_row3\" class=\"row_heading level0 row3\" >B_nr</th>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col0\" class=\"data row3 col0\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col1\" class=\"data row3 col1\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col2\" class=\"data row3 col2\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col3\" class=\"data row3 col3\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col4\" class=\"data row3 col4\" >0.750000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col5\" class=\"data row3 col5\" >0.250000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col6\" class=\"data row3 col6\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col7\" class=\"data row3 col7\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col8\" class=\"data row3 col8\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row3_col9\" class=\"data row3 col9\" >0.000000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966level0_row4\" class=\"row_heading level0 row4\" >M_nr</th>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col0\" class=\"data row4 col0\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col1\" class=\"data row4 col1\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col2\" class=\"data row4 col2\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col3\" class=\"data row4 col3\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col4\" class=\"data row4 col4\" >0.180000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col5\" class=\"data row4 col5\" >0.820000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col6\" class=\"data row4 col6\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col7\" class=\"data row4 col7\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col8\" class=\"data row4 col8\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row4_col9\" class=\"data row4 col9\" >0.000000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966level0_row5\" class=\"row_heading level0 row5\" >E_nr</th>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col0\" class=\"data row5 col0\" >0.010000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col1\" class=\"data row5 col1\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col2\" class=\"data row5 col2\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col3\" class=\"data row5 col3\" >0.030000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col4\" class=\"data row5 col4\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col5\" class=\"data row5 col5\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col6\" class=\"data row5 col6\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col7\" class=\"data row5 col7\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col8\" class=\"data row5 col8\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row5_col9\" class=\"data row5 col9\" >0.960000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966level0_row6\" class=\"row_heading level0 row6\" >B_ns</th>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col0\" class=\"data row6 col0\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col1\" class=\"data row6 col1\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col2\" class=\"data row6 col2\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col3\" class=\"data row6 col3\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col4\" class=\"data row6 col4\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col5\" class=\"data row6 col5\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col6\" class=\"data row6 col6\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col7\" class=\"data row6 col7\" >0.370000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col8\" class=\"data row6 col8\" >0.630000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row6_col9\" class=\"data row6 col9\" >0.000000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966level0_row7\" class=\"row_heading level0 row7\" >M_ns</th>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col0\" class=\"data row7 col0\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col1\" class=\"data row7 col1\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col2\" class=\"data row7 col2\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col3\" class=\"data row7 col3\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col4\" class=\"data row7 col4\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col5\" class=\"data row7 col5\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col6\" class=\"data row7 col6\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col7\" class=\"data row7 col7\" >0.390000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col8\" class=\"data row7 col8\" >0.610000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row7_col9\" class=\"data row7 col9\" >0.000000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966level0_row8\" class=\"row_heading level0 row8\" >E_ns</th>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col0\" class=\"data row8 col0\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col1\" class=\"data row8 col1\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col2\" class=\"data row8 col2\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col3\" class=\"data row8 col3\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col4\" class=\"data row8 col4\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col5\" class=\"data row8 col5\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col6\" class=\"data row8 col6\" >0.050000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col7\" class=\"data row8 col7\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col8\" class=\"data row8 col8\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row8_col9\" class=\"data row8 col9\" >0.940000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966level0_row9\" class=\"row_heading level0 row9\" >O</th>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col0\" class=\"data row9 col0\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col1\" class=\"data row9 col1\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col2\" class=\"data row9 col2\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col3\" class=\"data row9 col3\" >0.010000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col4\" class=\"data row9 col4\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col5\" class=\"data row9 col5\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col6\" class=\"data row9 col6\" >0.010000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col7\" class=\"data row9 col7\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col8\" class=\"data row9 col8\" >0.000000</td>\n",
       "                        <td id=\"T_cf09af2a_9ff3_11ea_9256_6f0258d5b966row9_col9\" class=\"data row9 col9\" >0.980000</td>\n",
       "            </tr>\n",
       "    </tbody></table>"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x7fded3f53c90>"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "# 转移矩阵，给定前一个标记的标签，后一个标记的标签的概率分布\n",
    "\n",
    "index = [\n",
    "    'B_nt', 'M_nt', 'E_nt', 'B_nr', 'M_nr', 'E_nr', 'B_ns', 'M_ns', 'E_ns', 'O'\n",
    "]\n",
    "transitions = pd.DataFrame(B, index=idx2tag.values(), columns=idx2tag.values())\n",
    "transitions.reindex(index, axis=0).reindex(index, axis=1).round(\n",
    "    2).style.applymap(lambda v: 'background-color: %s' % '#B0C4DE'\n",
    "                      if v > 0 else 'background-color: %s' % '#FFFFFF')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 从上表中，通过语料训练得到的转移矩阵，可以看出，连续的两个标签之间的联合概率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:29:16.503117Z",
     "start_time": "2020-05-27T08:29:16.491589Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style  type=\"text/css\" >\n",
       "    #T_2718fa40_9ff4_11ea_9256_6f0258d5b966row0_col0 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_2718fa40_9ff4_11ea_9256_6f0258d5b966row1_col0 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_2718fa40_9ff4_11ea_9256_6f0258d5b966row2_col0 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_2718fa40_9ff4_11ea_9256_6f0258d5b966row3_col0 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_2718fa40_9ff4_11ea_9256_6f0258d5b966row4_col0 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_2718fa40_9ff4_11ea_9256_6f0258d5b966row5_col0 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_2718fa40_9ff4_11ea_9256_6f0258d5b966row6_col0 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }    #T_2718fa40_9ff4_11ea_9256_6f0258d5b966row7_col0 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_2718fa40_9ff4_11ea_9256_6f0258d5b966row8_col0 {\n",
       "            background-color:  #FFFFFF;\n",
       "        }    #T_2718fa40_9ff4_11ea_9256_6f0258d5b966row9_col0 {\n",
       "            background-color:  #B0C4DE;\n",
       "        }</style><table id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966\" ><thead>    <tr>        <th class=\"blank level0\" ></th>        <th class=\"col_heading level0 col0\" >0</th>    </tr></thead><tbody>\n",
       "                <tr>\n",
       "                        <th id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966level0_row0\" class=\"row_heading level0 row0\" >B_nt</th>\n",
       "                        <td id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966row0_col0\" class=\"data row0 col0\" >0.030000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966level0_row1\" class=\"row_heading level0 row1\" >M_nt</th>\n",
       "                        <td id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966row1_col0\" class=\"data row1 col0\" >0.000000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966level0_row2\" class=\"row_heading level0 row2\" >E_nt</th>\n",
       "                        <td id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966row2_col0\" class=\"data row2 col0\" >0.000000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966level0_row3\" class=\"row_heading level0 row3\" >B_nr</th>\n",
       "                        <td id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966row3_col0\" class=\"data row3 col0\" >0.060000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966level0_row4\" class=\"row_heading level0 row4\" >M_nr</th>\n",
       "                        <td id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966row4_col0\" class=\"data row4 col0\" >0.000000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966level0_row5\" class=\"row_heading level0 row5\" >E_nr</th>\n",
       "                        <td id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966row5_col0\" class=\"data row5 col0\" >0.000000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966level0_row6\" class=\"row_heading level0 row6\" >B_ns</th>\n",
       "                        <td id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966row6_col0\" class=\"data row6 col0\" >0.040000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966level0_row7\" class=\"row_heading level0 row7\" >M_ns</th>\n",
       "                        <td id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966row7_col0\" class=\"data row7 col0\" >0.000000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966level0_row8\" class=\"row_heading level0 row8\" >E_ns</th>\n",
       "                        <td id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966row8_col0\" class=\"data row8 col0\" >0.000000</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966level0_row9\" class=\"row_heading level0 row9\" >O</th>\n",
       "                        <td id=\"T_2718fa40_9ff4_11ea_9256_6f0258d5b966row9_col0\" class=\"data row9 col0\" >0.870000</td>\n",
       "            </tr>\n",
       "    </tbody></table>"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x7fded2c08110>"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 句首标记的标签分布\n",
    "\n",
    "start_status = pd.DataFrame(pi, index=idx2tag.values())\n",
    "start_status.reindex(index, axis=0).round(2).style.applymap(\n",
    "    lambda v: 'background-color: %s' % '#B0C4DE'\n",
    "    if v > 0 else 'background-color: %s' % '#FFFFFF')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 句首单字的标签的概率分布"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 评估性能"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:33:58.609739Z",
     "start_time": "2020-05-27T08:33:58.587826Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "train len: 24271\n",
      "test len: 7585\n",
      "valid len: 6068\n"
     ]
    }
   ],
   "source": [
    "import pickle\n",
    "\n",
    "pickle_path = '../datasets/ner/renmin/renmindata.pkl'\n",
    "with open(pickle_path, 'rb') as inp:\n",
    "    word2id = pickle.load(inp)\n",
    "    id2word = pickle.load(inp)\n",
    "    tag2id = pickle.load(inp)\n",
    "    id2tag = pickle.load(inp)\n",
    "    x_train = pickle.load(inp)\n",
    "    y_train = pickle.load(inp)\n",
    "    \n",
    "    # 测试数据集\n",
    "    x_test = pickle.load(inp)\n",
    "    y_test = pickle.load(inp)\n",
    "    \n",
    "    x_valid = pickle.load(inp)\n",
    "    y_valid = pickle.load(inp)\n",
    "print(\"train len:\", len(x_train))\n",
    "print(\"test len:\", len(x_test))\n",
    "print(\"valid len:\", len(x_valid))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:33:59.614338Z",
     "start_time": "2020-05-27T08:33:59.608491Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([ 3, 33,  5,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,\n",
       "         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,\n",
       "         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,\n",
       "         0,  0,  0,  0,  0,  0,  0,  0,  0]),\n",
       " array([3, 3, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
       "        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
       "        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]))"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_test[0], y_test[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:35:22.973083Z",
     "start_time": "2020-05-27T08:35:22.965240Z"
    }
   },
   "outputs": [],
   "source": [
    "def log_(v):\n",
    "    return np.log(v + 0.000001)\n",
    "\n",
    "\n",
    "# 解码\n",
    "def viterbi_decode(x, pi, A, B):\n",
    "\n",
    "    T = len(x)\n",
    "    N = len(tag2idx)\n",
    "\n",
    "    dp = np.full((T, N), float('-inf'))\n",
    "    ptr = np.zeros_like(dp, dtype=np.int32)\n",
    "\n",
    "\n",
    "    dp[0] = log_(pi) + log_(A[:, x[0]])\n",
    "\n",
    "    for i in range(1, T):\n",
    "        v = dp[i - 1].reshape(-1, 1) + log_(B)\n",
    "        dp[i] = np.max(v, axis=0) + log_(A[:, x[i]])\n",
    "        ptr[i] = np.argmax(v, axis=0)\n",
    "        \n",
    "\n",
    "    best_seq = [0] * T\n",
    "    best_seq[-1] = np.argmax(dp[-1])\n",
    "    for i in range(T - 2, -1, -1):\n",
    "        best_seq[i] = ptr[i + 1][best_seq[i + 1]]\n",
    "    \n",
    "    return best_seq"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:35:23.793553Z",
     "start_time": "2020-05-27T08:35:23.786685Z"
    }
   },
   "outputs": [],
   "source": [
    "from sklearn.metrics import precision_score, recall_score, f1_score, classification_report\n",
    "\n",
    "\n",
    "def test(x_test, y_test):\n",
    "    preds, labels = [], []\n",
    "    for index, x in enumerate(x_test):\n",
    "        x = x[:sum(x > 0)]\n",
    "        y_pred = viterbi_decode(x, pi, A, B)\n",
    "        y_true = y_test[index][:sum(x > 0)]\n",
    "\n",
    "        preds.extend(y_pred)\n",
    "        labels.extend(y_true)\n",
    "\n",
    "    # 损失值与评测指标\n",
    "    precision = precision_score(labels, preds, average='macro')\n",
    "    recall = recall_score(labels, preds, average='macro')\n",
    "    f1 = f1_score(labels, preds, average='macro')\n",
    "    report = classification_report(labels, preds)\n",
    "    print(report)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:35:27.491503Z",
     "start_time": "2020-05-27T08:35:24.806362Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.73      0.69      0.71      2151\n",
      "           1       0.74      0.75      0.74      8090\n",
      "           2       0.89      0.78      0.83      3965\n",
      "           3       0.94      0.96      0.95     77532\n",
      "           4       0.92      0.83      0.87      3964\n",
      "           5       0.83      0.80      0.81      4522\n",
      "           6       0.66      0.70      0.68      2691\n",
      "           7       0.80      0.76      0.78      4524\n",
      "           8       0.88      0.84      0.86      3654\n",
      "           9       0.75      0.74      0.74      2146\n",
      "\n",
      "    accuracy                           0.90    113239\n",
      "   macro avg       0.81      0.78      0.80    113239\n",
      "weighted avg       0.90      0.90      0.90    113239\n",
      "\n"
     ]
    }
   ],
   "source": [
    "test(x_test, y_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 进行预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 文本向量化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:30:17.527719Z",
     "start_time": "2020-05-27T08:30:17.520235Z"
    }
   },
   "outputs": [],
   "source": [
    "import re, pickle\n",
    "\n",
    "# 文本向量化\n",
    "class Tokenizer:\n",
    "    def __init__(self, vocab_file):\n",
    "        with open(vocab_file, 'rb') as inp:\n",
    "            self.token2idx = pickle.load(inp)\n",
    "            self.idx2token = pickle.load(inp)\n",
    "\n",
    "    def encode(self, text, maxlen):\n",
    "        seqs = re.split('[，。！？、‘’“”:]', text.strip())\n",
    "        \n",
    "        # 将文本转换成索引\n",
    "        seq_ids = []\n",
    "        for seq in seqs:\n",
    "            token_ids = []\n",
    "            if seq:\n",
    "                for char in seq:\n",
    "                    if char not in self.token2idx:\n",
    "                        token_ids.append(self.token2idx['[unknown]'])\n",
    "                    else:\n",
    "                        token_ids.append(self.token2idx[char])\n",
    "                seq_ids.append(token_ids)\n",
    "        \n",
    "        # 等长化处理\n",
    "        num_samples = len(seq_ids)\n",
    "        x = np.full((num_samples, maxlen), 0., dtype=np.int64)\n",
    "        for idx, s in enumerate(seq_ids):\n",
    "            trunc = np.array(s[:maxlen], dtype=np.int64)\n",
    "            x[idx, :len(trunc)] = trunc\n",
    "        return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:30:19.471315Z",
     "start_time": "2020-05-27T08:30:19.460539Z"
    }
   },
   "outputs": [],
   "source": [
    "vocab_file = \"../datasets/ner/renmin/vocab.pkl\"\n",
    "tokenizer = Tokenizer(vocab_file)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:59:53.344109Z",
     "start_time": "2020-05-27T08:59:53.338168Z"
    }
   },
   "outputs": [],
   "source": [
    "text = \"新冠肺炎疫情发生后，以习近平同志为核心的党中央将疫情防控作为头等大事来抓，习近平\\\n",
    "总书记亲自指挥、亲自部署，坚持把人民生命安全和身体健康放在第一位，领导全党全军全国各族人民打好疫情\\\n",
    "防控的人民战争、总体战、阻击战。经过艰苦卓绝的努力，武汉保卫战、湖北保卫战取得决定性成果，疫情防控\\\n",
    "阻击战取得重大战略成果，统筹推进疫情防控和经济社会发展工作取得积极成效。\"\n",
    "\n",
    "tokenizer.encode(text, maxlen=30);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 进行预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:42:25.676533Z",
     "start_time": "2020-05-27T08:42:25.671270Z"
    }
   },
   "outputs": [],
   "source": [
    "def predict(input_ids):\n",
    "    res = []\n",
    "    for idx, x in enumerate(input_ids):\n",
    "        x = x[x > 0]\n",
    "        y_pred = viterbi_decode(x, pi, A, B)\n",
    "        res.append(y_pred)\n",
    "    return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:42:26.314948Z",
     "start_time": "2020-05-27T08:42:26.304015Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[3, 3, 3, 3, 3, 3, 3, 3, 3],\n",
       " [3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  9,\n",
       "  1,\n",
       "  0,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3,\n",
       "  3],\n",
       " [3, 3, 3, 3, 3, 3, 3, 3, 3, 3],\n",
       " [3, 3, 3, 3],\n",
       " [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3],\n",
       " [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3],\n",
       " [3, 3, 3],\n",
       " [3, 3, 3],\n",
       " [3, 3, 3, 3, 3, 3, 3, 3, 3],\n",
       " [9, 1, 1, 1, 1],\n",
       " [5, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3],\n",
       " [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3],\n",
       " [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]]"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "input_ids = tokenizer.encode(text, maxlen=30)\n",
    "predict(input_ids)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:41:59.964187Z",
     "start_time": "2020-05-27T08:41:59.958009Z"
    }
   },
   "source": [
    "### 预测向量转标签序列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:50:42.404319Z",
     "start_time": "2020-05-27T08:50:42.395889Z"
    }
   },
   "outputs": [],
   "source": [
    "class Parser:\n",
    "    def __init__(self, tags_file):\n",
    "        with open(tags_file, \"rb\") as inp:\n",
    "            self.tag2idx = pickle.load(inp)\n",
    "            self.idx2tag = pickle.load(inp)\n",
    "\n",
    "    def decode(self, text, paths):\n",
    "\n",
    "        seqs = re.split('[，。！？、‘’“”:]', text)\n",
    "        labels = [[self.idx2tag[idx] for idx in seq] for seq in paths]\n",
    "\n",
    "        res = []\n",
    "        for sent, tags in zip(seqs, labels):\n",
    "            print(tags)\n",
    "            tags = self._correct_tags(tags)\n",
    "            print(tags)\n",
    "            print('-'*100)\n",
    "            res.append(list(zip(sent, tags)))\n",
    "        return res\n",
    "\n",
    "    def _correct_tags(self, tags):\n",
    "        stack = []\n",
    "        for idx, tag in enumerate(tags):\n",
    "            # 判断标签是否合理\n",
    "            if tag.startswith(\"B\"):\n",
    "                stack.append(idx)\n",
    "            elif tag.startswith(\"M\") and stack and tags[\n",
    "                    stack[-1]] == 'B_' + tag[2:]:\n",
    "                continue\n",
    "            elif tag.startswith(\"E\") and stack and tags[\n",
    "                    stack[-1]] == 'B_' + tag[2:]:\n",
    "                stack.pop()\n",
    "            else:\n",
    "                stack.append(idx)\n",
    "\n",
    "        for idx in stack:\n",
    "            tags[idx] = 'O'\n",
    "        return tags"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:50:43.129122Z",
     "start_time": "2020-05-27T08:50:43.113695Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "----------------------------------------------------------------------------------------------------\n",
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'B_nt', 'M_nt', 'E_nt', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'B_nt', 'M_nt', 'E_nt', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "----------------------------------------------------------------------------------------------------\n",
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "----------------------------------------------------------------------------------------------------\n",
      "['O', 'O', 'O', 'O']\n",
      "['O', 'O', 'O', 'O']\n",
      "----------------------------------------------------------------------------------------------------\n",
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "----------------------------------------------------------------------------------------------------\n",
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "----------------------------------------------------------------------------------------------------\n",
      "['O', 'O', 'O']\n",
      "['O', 'O', 'O']\n",
      "----------------------------------------------------------------------------------------------------\n",
      "['O', 'O', 'O']\n",
      "['O', 'O', 'O']\n",
      "----------------------------------------------------------------------------------------------------\n",
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "----------------------------------------------------------------------------------------------------\n",
      "['B_nt', 'M_nt', 'M_nt', 'M_nt', 'M_nt']\n",
      "['O', 'M_nt', 'M_nt', 'M_nt', 'M_nt']\n",
      "----------------------------------------------------------------------------------------------------\n",
      "['B_ns', 'E_ns', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "['B_ns', 'E_ns', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "----------------------------------------------------------------------------------------------------\n",
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "----------------------------------------------------------------------------------------------------\n",
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']\n",
      "----------------------------------------------------------------------------------------------------\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[[('新', 'O'),\n",
       "  ('冠', 'O'),\n",
       "  ('肺', 'O'),\n",
       "  ('炎', 'O'),\n",
       "  ('疫', 'O'),\n",
       "  ('情', 'O'),\n",
       "  ('发', 'O'),\n",
       "  ('生', 'O'),\n",
       "  ('后', 'O')],\n",
       " [('以', 'O'),\n",
       "  ('习', 'O'),\n",
       "  ('近', 'O'),\n",
       "  ('平', 'O'),\n",
       "  ('同', 'O'),\n",
       "  ('志', 'O'),\n",
       "  ('为', 'O'),\n",
       "  ('核', 'O'),\n",
       "  ('心', 'O'),\n",
       "  ('的', 'O'),\n",
       "  ('党', 'B_nt'),\n",
       "  ('中', 'M_nt'),\n",
       "  ('央', 'E_nt'),\n",
       "  ('将', 'O'),\n",
       "  ('疫', 'O'),\n",
       "  ('情', 'O'),\n",
       "  ('防', 'O'),\n",
       "  ('控', 'O'),\n",
       "  ('作', 'O'),\n",
       "  ('为', 'O'),\n",
       "  ('头', 'O'),\n",
       "  ('等', 'O'),\n",
       "  ('大', 'O'),\n",
       "  ('事', 'O'),\n",
       "  ('来', 'O'),\n",
       "  ('抓', 'O')],\n",
       " [('习', 'O'),\n",
       "  ('近', 'O'),\n",
       "  ('平', 'O'),\n",
       "  ('总', 'O'),\n",
       "  ('书', 'O'),\n",
       "  ('记', 'O'),\n",
       "  ('亲', 'O'),\n",
       "  ('自', 'O'),\n",
       "  ('指', 'O'),\n",
       "  ('挥', 'O')],\n",
       " [('亲', 'O'), ('自', 'O'), ('部', 'O'), ('署', 'O')],\n",
       " [('坚', 'O'),\n",
       "  ('持', 'O'),\n",
       "  ('把', 'O'),\n",
       "  ('人', 'O'),\n",
       "  ('民', 'O'),\n",
       "  ('生', 'O'),\n",
       "  ('命', 'O'),\n",
       "  ('安', 'O'),\n",
       "  ('全', 'O'),\n",
       "  ('和', 'O'),\n",
       "  ('身', 'O'),\n",
       "  ('体', 'O'),\n",
       "  ('健', 'O'),\n",
       "  ('康', 'O'),\n",
       "  ('放', 'O'),\n",
       "  ('在', 'O'),\n",
       "  ('第', 'O'),\n",
       "  ('一', 'O'),\n",
       "  ('位', 'O')],\n",
       " [('领', 'O'),\n",
       "  ('导', 'O'),\n",
       "  ('全', 'O'),\n",
       "  ('党', 'O'),\n",
       "  ('全', 'O'),\n",
       "  ('军', 'O'),\n",
       "  ('全', 'O'),\n",
       "  ('国', 'O'),\n",
       "  ('各', 'O'),\n",
       "  ('族', 'O'),\n",
       "  ('人', 'O'),\n",
       "  ('民', 'O'),\n",
       "  ('打', 'O'),\n",
       "  ('好', 'O'),\n",
       "  ('疫', 'O'),\n",
       "  ('情', 'O'),\n",
       "  ('防', 'O'),\n",
       "  ('控', 'O'),\n",
       "  ('的', 'O'),\n",
       "  ('人', 'O'),\n",
       "  ('民', 'O'),\n",
       "  ('战', 'O'),\n",
       "  ('争', 'O')],\n",
       " [('总', 'O'), ('体', 'O'), ('战', 'O')],\n",
       " [('阻', 'O'), ('击', 'O'), ('战', 'O')],\n",
       " [('经', 'O'),\n",
       "  ('过', 'O'),\n",
       "  ('艰', 'O'),\n",
       "  ('苦', 'O'),\n",
       "  ('卓', 'O'),\n",
       "  ('绝', 'O'),\n",
       "  ('的', 'O'),\n",
       "  ('努', 'O'),\n",
       "  ('力', 'O')],\n",
       " [('武', 'O'), ('汉', 'M_nt'), ('保', 'M_nt'), ('卫', 'M_nt'), ('战', 'M_nt')],\n",
       " [('湖', 'B_ns'),\n",
       "  ('北', 'E_ns'),\n",
       "  ('保', 'O'),\n",
       "  ('卫', 'O'),\n",
       "  ('战', 'O'),\n",
       "  ('取', 'O'),\n",
       "  ('得', 'O'),\n",
       "  ('决', 'O'),\n",
       "  ('定', 'O'),\n",
       "  ('性', 'O'),\n",
       "  ('成', 'O'),\n",
       "  ('果', 'O')],\n",
       " [('疫', 'O'),\n",
       "  ('情', 'O'),\n",
       "  ('防', 'O'),\n",
       "  ('控', 'O'),\n",
       "  ('阻', 'O'),\n",
       "  ('击', 'O'),\n",
       "  ('战', 'O'),\n",
       "  ('取', 'O'),\n",
       "  ('得', 'O'),\n",
       "  ('重', 'O'),\n",
       "  ('大', 'O'),\n",
       "  ('战', 'O'),\n",
       "  ('略', 'O'),\n",
       "  ('成', 'O'),\n",
       "  ('果', 'O')],\n",
       " [('统', 'O'),\n",
       "  ('筹', 'O'),\n",
       "  ('推', 'O'),\n",
       "  ('进', 'O'),\n",
       "  ('疫', 'O'),\n",
       "  ('情', 'O'),\n",
       "  ('防', 'O'),\n",
       "  ('控', 'O'),\n",
       "  ('和', 'O'),\n",
       "  ('经', 'O'),\n",
       "  ('济', 'O'),\n",
       "  ('社', 'O'),\n",
       "  ('会', 'O'),\n",
       "  ('发', 'O'),\n",
       "  ('展', 'O'),\n",
       "  ('工', 'O'),\n",
       "  ('作', 'O'),\n",
       "  ('取', 'O'),\n",
       "  ('得', 'O'),\n",
       "  ('积', 'O'),\n",
       "  ('极', 'O'),\n",
       "  ('成', 'O'),\n",
       "  ('效', 'O')]]"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tags_file = \"../datasets/ner/renmin/tags.pkl\"\n",
    "parser = Parser(tags_file)\n",
    "\n",
    "paths = predict(input_ids)\n",
    "\n",
    "parser.decode(text, paths)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:48:17.911602Z",
     "start_time": "2020-05-27T08:48:17.906209Z"
    }
   },
   "outputs": [],
   "source": [
    "ttt = [('武', 'O'), ('汉', 'M_nt'), ('保', 'M_nt'), ('卫', 'M_nt'), ('战', 'M_nt')]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:48:35.014245Z",
     "start_time": "2020-05-27T08:48:35.008848Z"
    }
   },
   "outputs": [],
   "source": [
    "tttags = [tmp[1] for tmp in ttt]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:48:41.893755Z",
     "start_time": "2020-05-27T08:48:41.884490Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['O', 'M_nt', 'M_nt', 'M_nt', 'M_nt']"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tttags"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T08:49:15.872491Z",
     "start_time": "2020-05-27T08:49:15.866571Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['O', 'O', 'O', 'O', 'O']"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "parser._correct_tags(tttags)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T09:03:50.406670Z",
     "start_time": "2020-05-27T09:03:50.401192Z"
    }
   },
   "outputs": [],
   "source": [
    "seqs = re.findall('[，。！？、‘’“”:]', text.strip())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T09:03:51.534999Z",
     "start_time": "2020-05-27T09:03:51.529327Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['，', '，', '、', '，', '，', '、', '、', '。', '，', '、', '，', '，', '。']"
      ]
     },
     "execution_count": 101,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "seqs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T09:03:32.184273Z",
     "start_time": "2020-05-27T09:03:32.178527Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'，'"
      ]
     },
     "execution_count": 98,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "text[9]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T09:03:39.083756Z",
     "start_time": "2020-05-27T09:03:39.074519Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'以'"
      ]
     },
     "execution_count": 99,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "text[10]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T09:20:09.577637Z",
     "start_time": "2020-05-27T09:20:09.571912Z"
    }
   },
   "outputs": [],
   "source": [
    "import string"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T09:20:21.883845Z",
     "start_time": "2020-05-27T09:20:21.878414Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'!\"#$%&\\'()*+,-./:;<=>?@[\\\\]^_`{|}~'"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "string.punctuation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Tokenizer:\n",
    "    def __init__(self, vocab_file):\n",
    "        with open(vocab_file, 'rb') as inp:\n",
    "            self.token2idx = pickle.load(inp)\n",
    "            self.idx2token = pickle.load(inp)\n",
    "\n",
    "    def encode(self, text):\n",
    "        sep = set('，。！？、‘’“”:')\n",
    "        \n",
    "        res = {}\n",
    "        \n",
    "        start = 0\n",
    "        end = 0\n",
    "        for idx, char in enumerate(text):\n",
    "            end = idx\n",
    "            if char in sep:\n",
    "                ids = [self.token2idx[char] for char in text[start:end]]\n",
    "                res[(start,end)] = ids\n",
    "                start\n",
    "                \n",
    "                \n",
    "            \n",
    "        seqs = re.split('[，。！？、‘’“”:]', text.strip())\n",
    "        \n",
    "        # 将文本转换成索引\n",
    "        seq_ids = []\n",
    "        for seq in seqs:\n",
    "            token_ids = []\n",
    "            if seq:\n",
    "                for char in seq:\n",
    "                    if char not in self.token2idx:\n",
    "                        token_ids.append(self.token2idx['[unknown]'])\n",
    "                    else:\n",
    "                        token_ids.append(self.token2idx[char])\n",
    "                seq_ids.append(token_ids)\n",
    "        \n",
    "        # 等长化处理\n",
    "        num_samples = len(seq_ids)\n",
    "        x = np.full((num_samples, maxlen), 0., dtype=np.int64)\n",
    "        for idx, s in enumerate(seq_ids):\n",
    "            trunc = np.array(s[:maxlen], dtype=np.int64)\n",
    "            x[idx, :len(trunc)] = trunc\n",
    "        return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T09:41:02.669972Z",
     "start_time": "2020-05-27T09:41:02.665213Z"
    }
   },
   "outputs": [],
   "source": [
    "text = \"新冠肺炎疫情发生后，以习近平同志为核心的党中央将疫情防控作为头等大事来抓，习近平\\\n",
    "总书记亲自指挥、亲自部署，坚持把人民生命安全和身体健康放在第一位，领导全党全军全国各族人民打好疫情\\\n",
    "防控的人民战争、总体战、阻击战。经过艰苦卓绝的努力，武汉保卫战、湖北保卫战取得决定性成果，疫情防控\\\n",
    "阻击战取得重大战略成果，统筹推进疫情防控和经济社会发展工作取得积极成效。\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T09:41:03.888649Z",
     "start_time": "2020-05-27T09:41:03.874032Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[(0, 3), (1, 3), (2, 3), (3, 3), (4, 3), (5, 3), (6, 3), (7, 3), (8, 3)],\n",
       " [(10, 3),\n",
       "  (11, 3),\n",
       "  (12, 3),\n",
       "  (13, 3),\n",
       "  (14, 3),\n",
       "  (15, 3),\n",
       "  (16, 3),\n",
       "  (17, 3),\n",
       "  (18, 3),\n",
       "  (19, 3),\n",
       "  (20, 9),\n",
       "  (21, 1),\n",
       "  (22, 0),\n",
       "  (23, 3),\n",
       "  (24, 3),\n",
       "  (25, 3),\n",
       "  (26, 3),\n",
       "  (27, 3),\n",
       "  (28, 3),\n",
       "  (29, 3),\n",
       "  (30, 3),\n",
       "  (31, 3),\n",
       "  (32, 3),\n",
       "  (33, 3),\n",
       "  (34, 3),\n",
       "  (35, 3)],\n",
       " [(37, 3),\n",
       "  (38, 3),\n",
       "  (39, 3),\n",
       "  (40, 3),\n",
       "  (41, 3),\n",
       "  (42, 3),\n",
       "  (43, 3),\n",
       "  (44, 3),\n",
       "  (45, 3),\n",
       "  (46, 3)],\n",
       " [(48, 3), (49, 3), (50, 3), (51, 3)],\n",
       " [(53, 3),\n",
       "  (54, 3),\n",
       "  (55, 3),\n",
       "  (56, 3),\n",
       "  (57, 3),\n",
       "  (58, 3),\n",
       "  (59, 3),\n",
       "  (60, 3),\n",
       "  (61, 3),\n",
       "  (62, 3),\n",
       "  (63, 3),\n",
       "  (64, 3),\n",
       "  (65, 3),\n",
       "  (66, 3),\n",
       "  (67, 3),\n",
       "  (68, 3),\n",
       "  (69, 3),\n",
       "  (70, 3),\n",
       "  (71, 3)],\n",
       " [(73, 3),\n",
       "  (74, 3),\n",
       "  (75, 3),\n",
       "  (76, 3),\n",
       "  (77, 3),\n",
       "  (78, 3),\n",
       "  (79, 3),\n",
       "  (80, 3),\n",
       "  (81, 3),\n",
       "  (82, 3),\n",
       "  (83, 3),\n",
       "  (84, 3),\n",
       "  (85, 3),\n",
       "  (86, 3),\n",
       "  (87, 3),\n",
       "  (88, 3),\n",
       "  (89, 3),\n",
       "  (90, 3),\n",
       "  (91, 3),\n",
       "  (92, 3),\n",
       "  (93, 3),\n",
       "  (94, 3),\n",
       "  (95, 3)],\n",
       " [(97, 3), (98, 3), (99, 3)],\n",
       " [(101, 3), (102, 3), (103, 3)],\n",
       " [(105, 3),\n",
       "  (106, 3),\n",
       "  (107, 3),\n",
       "  (108, 3),\n",
       "  (109, 3),\n",
       "  (110, 3),\n",
       "  (111, 3),\n",
       "  (112, 3),\n",
       "  (113, 3)],\n",
       " [(115, 9), (116, 1), (117, 1), (118, 1), (119, 1)],\n",
       " [(121, 5),\n",
       "  (122, 7),\n",
       "  (123, 3),\n",
       "  (124, 3),\n",
       "  (125, 3),\n",
       "  (126, 3),\n",
       "  (127, 3),\n",
       "  (128, 3),\n",
       "  (129, 3),\n",
       "  (130, 3),\n",
       "  (131, 3),\n",
       "  (132, 3)],\n",
       " [(134, 3),\n",
       "  (135, 3),\n",
       "  (136, 3),\n",
       "  (137, 3),\n",
       "  (138, 3),\n",
       "  (139, 3),\n",
       "  (140, 3),\n",
       "  (141, 3),\n",
       "  (142, 3),\n",
       "  (143, 3),\n",
       "  (144, 3),\n",
       "  (145, 3),\n",
       "  (146, 3),\n",
       "  (147, 3),\n",
       "  (148, 3)],\n",
       " [(150, 3),\n",
       "  (151, 3),\n",
       "  (152, 3),\n",
       "  (153, 3),\n",
       "  (154, 3),\n",
       "  (155, 3),\n",
       "  (156, 3),\n",
       "  (157, 3),\n",
       "  (158, 3),\n",
       "  (159, 3),\n",
       "  (160, 3),\n",
       "  (161, 3),\n",
       "  (162, 3),\n",
       "  (163, 3),\n",
       "  (164, 3),\n",
       "  (165, 3),\n",
       "  (166, 3),\n",
       "  (167, 3),\n",
       "  (168, 3),\n",
       "  (169, 3),\n",
       "  (170, 3),\n",
       "  (171, 3),\n",
       "  (172, 3)]]"
      ]
     },
     "execution_count": 112,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res = []\n",
    "start = 0\n",
    "for m in re.finditer('[，。！？、‘’“”:]', text):\n",
    "    end = m.span()[0]\n",
    "    seg = text[start:end]\n",
    "    seg_ids = [token2idx[token] for token in seg]\n",
    "    seg_labels = viterbi_decode(seg_ids, pi, A, B)\n",
    "    res.append(list(zip(list(range(start, end)), seg_labels)))\n",
    "    start = m.span()[1]\n",
    "res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-27T09:41:22.841554Z",
     "start_time": "2020-05-27T09:41:22.822440Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "新 O\n",
      "冠 O\n",
      "肺 O\n",
      "炎 O\n",
      "疫 O\n",
      "情 O\n",
      "发 O\n",
      "生 O\n",
      "后 O\n",
      "以 O\n",
      "习 O\n",
      "近 O\n",
      "平 O\n",
      "同 O\n",
      "志 O\n",
      "为 O\n",
      "核 O\n",
      "心 O\n",
      "的 O\n",
      "党 B_nt\n",
      "中 M_nt\n",
      "央 E_nt\n",
      "将 O\n",
      "疫 O\n",
      "情 O\n",
      "防 O\n",
      "控 O\n",
      "作 O\n",
      "为 O\n",
      "头 O\n",
      "等 O\n",
      "大 O\n",
      "事 O\n",
      "来 O\n",
      "抓 O\n",
      "习 O\n",
      "近 O\n",
      "平 O\n",
      "总 O\n",
      "书 O\n",
      "记 O\n",
      "亲 O\n",
      "自 O\n",
      "指 O\n",
      "挥 O\n",
      "亲 O\n",
      "自 O\n",
      "部 O\n",
      "署 O\n",
      "坚 O\n",
      "持 O\n",
      "把 O\n",
      "人 O\n",
      "民 O\n",
      "生 O\n",
      "命 O\n",
      "安 O\n",
      "全 O\n",
      "和 O\n",
      "身 O\n",
      "体 O\n",
      "健 O\n",
      "康 O\n",
      "放 O\n",
      "在 O\n",
      "第 O\n",
      "一 O\n",
      "位 O\n",
      "领 O\n",
      "导 O\n",
      "全 O\n",
      "党 O\n",
      "全 O\n",
      "军 O\n",
      "全 O\n",
      "国 O\n",
      "各 O\n",
      "族 O\n",
      "人 O\n",
      "民 O\n",
      "打 O\n",
      "好 O\n",
      "疫 O\n",
      "情 O\n",
      "防 O\n",
      "控 O\n",
      "的 O\n",
      "人 O\n",
      "民 O\n",
      "战 O\n",
      "争 O\n",
      "总 O\n",
      "体 O\n",
      "战 O\n",
      "阻 O\n",
      "击 O\n",
      "战 O\n",
      "经 O\n",
      "过 O\n",
      "艰 O\n",
      "苦 O\n",
      "卓 O\n",
      "绝 O\n",
      "的 O\n",
      "努 O\n",
      "力 O\n",
      "武 B_nt\n",
      "汉 M_nt\n",
      "保 M_nt\n",
      "卫 M_nt\n",
      "战 M_nt\n",
      "湖 B_ns\n",
      "北 E_ns\n",
      "保 O\n",
      "卫 O\n",
      "战 O\n",
      "取 O\n",
      "得 O\n",
      "决 O\n",
      "定 O\n",
      "性 O\n",
      "成 O\n",
      "果 O\n",
      "疫 O\n",
      "情 O\n",
      "防 O\n",
      "控 O\n",
      "阻 O\n",
      "击 O\n",
      "战 O\n",
      "取 O\n",
      "得 O\n",
      "重 O\n",
      "大 O\n",
      "战 O\n",
      "略 O\n",
      "成 O\n",
      "果 O\n",
      "统 O\n",
      "筹 O\n",
      "推 O\n",
      "进 O\n",
      "疫 O\n",
      "情 O\n",
      "防 O\n",
      "控 O\n",
      "和 O\n",
      "经 O\n",
      "济 O\n",
      "社 O\n",
      "会 O\n",
      "发 O\n",
      "展 O\n",
      "工 O\n",
      "作 O\n",
      "取 O\n",
      "得 O\n",
      "积 O\n",
      "极 O\n",
      "成 O\n",
      "效 O\n"
     ]
    }
   ],
   "source": [
    "for seg in res:\n",
    "    for idx, tag_id in seg:\n",
    "        print(text[idx], idx2tag[tag_id])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
